﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using OVS_SizeCalculation;
using OVS_TrajectoryCalculation;
using OVS_VideoRecorder;
using OVS_NotificationSender;
using OVS_FormsRecognition.Manager;
using OVS_FrontOffice.Manager;
using OVS.BusinessObjects;
using MjpegProcessor;
using System.Timers;
using OVS_FormsRecognition.Objects;
using System.Windows.Threading;
using System.Drawing;
using OVS_Tools;
using OVS.BLL;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using OVS_NotificationSender.Manager;
using OVS_VideoRecorder.Manager;
using OVS_TrajectoryCalculation.Manager;



namespace OVS_FormsRecognition
{


    /// <summary>
    /// Logique d'interaction pour FormsRecognitionMain.xaml
    /// </summary>
    public partial class FormsRecognitionMain : Window
    {


        #region Attributs
        private TrajectoryCalculationMain _TrajectoryCalculationMain;
        private VideoRecorderMain _VideoRecorderMain;
        private NotificationSenderMain _NotificationSenderMain;

        private int SelectedCam = -1;


        private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(typeof(FormsRecognitionMain));

        #endregion


        public FormsRecognitionMain()
        {
            InitializeComponent();

            FormsRecognitionManager.Instance.UpdateCameraDetectionSenderEvent += new FormsRecognitionManager.UpdateCameraDetectionSenderEventHandler(CallBackUpdateCameraDetectionSenderEvent);

            FrontOfficeManager.Instance.RegisterEventHandlers();

#if DEBUG
            // affichage des IHM des modules pour les tests
            // InitModules(this.Top);
#endif

            startCapture();

        }

        private void buttonInitModules_Click(object sender, RoutedEventArgs e)
        {

        }

        private void startCapture()
        {

            try
            {
                List<Camera> listCams = CameraBLL.Instance.GetCamerasEnabled();
                foreach (Camera myCam in listCams)
                {
                    addNewCamera(myCam.came_id, myCam.came_url, myCam.came_nom);
                }

                //addNewCamera(0, "http://192.168.1.68:9090/cam_1.cgi", "camName 1");
                //addNewCamera(1, "http://192.168.1.68:9090/cam_1.cgi", "camName 2");
                //addNewCamera(2, "http://192.168.1.68:9090/cam_1.cgi", "camName 3");
                //addNewCamera(3, "http://192.168.1.68:9090/cam_1.cgi", "camName 4");


                foreach (CameraFromMjpegDecoder camera in FormsRecognitionManager.Instance.listCamera)
                {
                    //if (camera.currentFrame != null)
                    //{


                    // Récupération des images a détecter pour cette camera
                    List<Image_Haar> HaartainningFiles = new List<Image_Haar>();
                    List<CameraImage_Haar> listCameraImage_Haar = CameraImage_HaarBLL.Instance.GetCameraImage_HaarsOfCamera(camera.CameraId);

                    if (listCameraImage_Haar.Count <= 0)
                        break;

                    foreach (CameraImage_Haar cameraImage_Haar in listCameraImage_Haar)
                    {
                        Image_Haar image_Haar = Image_HaarBLL.Instance.GetImage_Haar(cameraImage_Haar.Image_Haar_imha_id);

                        if (File.Exists(image_Haar.imha_fn))
                        {
                            HaartainningFiles.Add(image_Haar);
                        }
                    }

                    camera.HaartainningFilesListe = HaartainningFiles;
                    //}
                }


                //  DispatcherTimer setup
                DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
                dispatcherTimer.Tick += new EventHandler(UpdateCameraCapture);
                dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);
                dispatcherTimer.Start();

            }
            catch (Exception ex)
            {
                _Log.Debug(ex);
            }

        }

        /// <summary>
        /// Adds the new camera.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="camPath">The cam path.</param>
        private void addNewCamera(int id, string camPath, string camName)
        {
            if (id < 0) return;
            if (String.IsNullOrEmpty(camPath)) return;

            try
            {

                _Log.DebugFormat("addNewCamera(int {0}, string {1}, string {2}", id, camPath, camName);
                FormsRecognitionManager.Instance.AddNewCamera(id, camPath);

                System.Windows.Controls.Image imageCam = new System.Windows.Controls.Image();
                imageCam.Tag = id;
                imageCam.Height = 80;
                imageCam.Width = 120;
                imageCam.Stretch = Stretch.Uniform;
                imageCam.ToolTip = camName;


                ListCam.Items.Add(imageCam);
                ListCam.SelectionChanged += new SelectionChangedEventHandler(ListCam_SelectionChanged);

            }
            catch (Exception ex)
            {

                _Log.WarnFormat("addNewCamera(int {0}, string {1}): Exception {2}", id, camPath, ex);
            }
        }

        void ListCam_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListView list = sender as ListView;
            if (list != null)
            {
                System.Windows.Controls.Image image = (System.Windows.Controls.Image)list.Items[list.SelectedIndex];
                if (image != null)
                    SelectedCam = (int)image.Tag;
            }
        }

        // Specify what you want to happen when the Elapsed event is 
        // raised.
        /// <summary>
        /// Updates the camera capture.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void UpdateCameraCapture(object sender, EventArgs e)
        {
            if (FormsRecognitionManager.Instance.listCamera == null)
                return;
            if (FormsRecognitionManager.Instance.listCamera.Count <= 0)
                return;

            try
            {

                //double dblScaleFactor = sliderScall.Value;
                //labelScaleFactor.Content = String.Format("scaleFactor : {0}", sliderScall.Value);

                //int intMinNeighbors = (int)sliderNeighboor.Value;
                //labelMinNeighbors.Content = String.Format("minNeighbors : {0}", sliderNeighboor.Value);

                bool detectObject = false;
                if (checkBoxDetectObject.IsChecked == true)
                    detectObject = true;



                //  Method signature: 
                Parallel.ForEach(FormsRecognitionManager.Instance.listCamera, camera =>
                //foreach (CameraFromMjpegDecoder camera in FormsRecognitionManager.Instance.listCamera)
                //{
                {

                    if (camera.currentFrame == null)
                        return;

                    //camera.MjpegDecoder.Bitmap = ImageHelper.GetBitmap(camera.currentFrame);

                    if (camera.MjpegDecoder.Bitmap != null)
                    {
                        DetectEventArgs detectEventArgs = new DetectEventArgs();
                        detectEventArgs.bitmapSource = camera.MjpegDecoder.Bitmap;
                        detectEventArgs.camId = camera.CameraId;
                        //detectEventArgs.scaleFactor = dblScaleFactor;
                        //detectEventArgs.minNeighbors = intMinNeighbors;
                        detectEventArgs.detectObject = detectObject;


                        detectEventArgs.listHaarFilesToDetect = camera.HaartainningFilesListe;

                        FormsRecognitionManager.Instance.NewUpdateFromCamAllow(camera, detectEventArgs);
                        //_Log.DebugFormat("UpdateCameraCapture(id: {0})", camera.CameraId);
                    }
                    else
                    {
                        //_Log.DebugFormat("UpdateCameraCapture(id: {0} currentFrame ==  NULL)", camera.CameraId);
                    }
                });
                //}
            }
            catch (Exception ex)
            {
                MessageBox.Show("UpdateCameraCapture: Exception: " + ex);
            }
        }

        /// <summary>
        /// Calls the back size calculation start event.
        /// </summary>
        /// <param name="nullObject">The null object.</param>
        /// <param name="pSizeCalculationEventArgs">The <see cref="SizeCalculationEventArgs" /> instance containing the event data.</param>
        private void CallBackUpdateCameraDetectionSenderEvent(object nullObject, DetectEventArgs pDetectEventArgs)
        {
            try
            {
                UIThreadHelper.UIThread(this, delegate
                 {


                     //_Log.Debug("new event UpdateCameraDetectionSenderEvent !!!");

                     ImageSource imageSource = ImageHelper.CreateBitmapSourceFromBitmap(pDetectEventArgs.bitmapFromdetection);

                     foreach (System.Windows.Controls.Image imageCamera in ListCam.Items)
                     {

                         if (pDetectEventArgs.camId == (int)imageCamera.Tag)
                         {
                             imageCamera.Source = imageSource;

                             if (SelectedCam == pDetectEventArgs.camId)
                             {
                                 imageBoxSelectedCam.Source = imageSource;
                             }
                         }

                     }



                 });
            }
            catch (Exception ex)
            {
                _Log.Fatal("CallBackUpdateCameraDetectionSenderEvent: Exception: " + ex);
            }

        }

        private void FormRecognitionMainBase_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            foreach (CameraFromMjpegDecoder camObj in FormsRecognitionManager.Instance.listCamera)
            {               
                camObj.UnregisterListenner();
            }
            FormsRecognitionManager.Instance.listCamera = new List<CameraFromMjpegDecoder>();


           // FormsRecognitionManager.Instance.closeAllAlert();

            if (_NotificationSenderMain != null)
                _NotificationSenderMain.Close();
            if (_TrajectoryCalculationMain != null)
                _TrajectoryCalculationMain.Close();
            if (_VideoRecorderMain != null)
                _VideoRecorderMain.Close();


        }

        #region event Click show Module

        private void checkBoxNotificationSender_Click(object sender, RoutedEventArgs e)
        {
            double currentTop = this.Top;
            int margin = 10;

            if (checkBoxNotificationSender.IsChecked == true)
            {
                _NotificationSenderMain = new NotificationSenderMain();
                _NotificationSenderMain.WindowStartupLocation = WindowStartupLocation.Manual;
                _NotificationSenderMain.Left =  302 + margin;
                _NotificationSenderMain.Top = 0;
                _NotificationSenderMain.Width = this.Width - 302 - margin;
                _NotificationSenderMain.Height = this.Top - margin;
                _NotificationSenderMain.Show();
            }
            else
            {
                if (_NotificationSenderMain == null) return;

                _NotificationSenderMain.Close();
            }
        }

        private void checkBoxTrajectoryCalculationv_Click(object sender, RoutedEventArgs e)
        {
            double currentTop = this.Top;
            int margin = 10;

            if (checkBoxTrajectoryCalculationv.IsChecked == true)
            {
                _TrajectoryCalculationMain = new TrajectoryCalculationMain();
                _TrajectoryCalculationMain.WindowStartupLocation = WindowStartupLocation.Manual;
                _TrajectoryCalculationMain.Left = this.Left + margin + this.Width;
                _TrajectoryCalculationMain.Top = (((int)SystemParameters.PrimaryScreenHeight) / 2) + margin;
                _TrajectoryCalculationMain.Height = (((int)SystemParameters.PrimaryScreenHeight) / 2) - margin - 40;
                _TrajectoryCalculationMain.Width = SystemParameters.PrimaryScreenWidth - (_TrajectoryCalculationMain.Left);
                _TrajectoryCalculationMain.Show();
            }
            else
            {
                if (_TrajectoryCalculationMain == null) return;

                _TrajectoryCalculationMain.Close();
            }
        }

        private void checkBoxVideoRecorder_Click(object sender, RoutedEventArgs e)
        {            
            int margin = 10;

            if (checkBoxVideoRecorder.IsChecked == true)
            {
                _VideoRecorderMain = new VideoRecorderMain();
                _VideoRecorderMain.WindowStartupLocation = WindowStartupLocation.Manual;
                _VideoRecorderMain.Left = 0;
                _VideoRecorderMain.Top = this.Top + this.Height + margin;
                _VideoRecorderMain.Width = this.Width;
                _VideoRecorderMain.Height = ((int)SystemParameters.PrimaryScreenHeight) - _VideoRecorderMain.Top - 40;
                _VideoRecorderMain.Show();
            }
            else
            {
                if (_VideoRecorderMain == null) return;

                _VideoRecorderMain.Close();
            }
        }
        #endregion

        private void checkBoxDetectObject_Checked(object sender, RoutedEventArgs e)
        {
            if (!(bool) checkBoxDetectObject.IsChecked)
            {
                FormsRecognitionManager.Instance.closeAllAlert();
            }
        }










    }


}
